#include "iic.h"

// iic初始化
int32_t iic_init(iic_t *p)
{
    if (!p->ioinited)
        return -1;
    iic_stop(p);
    p->inited = 1;
    return 0;
}

int32_t iic_regsiter(iic_t *p, iic_iodrv_t *pdrv)
{
    p->io = *pdrv;
    p->ioinited = 1;
    return 0;
}

// 产生iic起始信号
int32_t iic_start(iic_t *p)
{
    if (!p->ioinited)
        return -1;
    p->io.wrsda(1);
    p->io.wrscl(1);
    p->io.dlyus(2);
    p->io.wrsda(0); 
    p->io.dlyus(2);
    p->io.wrscl(0);
    p->io.dlyus(2);
    return 0;
}

// 产生iic停止信号
int32_t iic_stop(iic_t *p)
{
    if (!p->ioinited)
        return -1;
    p->io.wrsda(0);
    p->io.dlyus(2);
    p->io.wrscl(1);
    p->io.dlyus(2);
    p->io.wrsda(1);
    p->io.dlyus(2);
    return 0;
}

// 产生ack应答
int32_t iic_ack(iic_t *p)
{
    if (!p->ioinited)
        return -1;
    p->io.wrsda(0);
    p->io.dlyus(2);
    p->io.wrscl(1);
    p->io.dlyus(2);
    p->io.wrscl(0);
    p->io.dlyus(2);
    p->io.wrsda(1);
    p->io.dlyus(2);
    return 0;
}

// 不产生ack应答
int32_t iic_nack(iic_t *p)
{
    if (!p->ioinited)
        return -1;
    p->io.wrsda(1);
    p->io.dlyus(2);
    p->io.wrscl(1);
    p->io.dlyus(2);
    p->io.wrscl(0);
    p->io.dlyus(2);
    return 0;
}


// 等待应答信号到来
// 返回值：1，接收应答失败
//         0，接收应答成功
int32_t iic_wait_ack(iic_t *p)
{
    uint8_t ucerrtime = 0;
    if (!p->ioinited)
        return -1;
    p->io.wrsda(1);
    p->io.dlyus(2);
    p->io.wrscl(1);
    p->io.dlyus(2);
    while (p->io.rdsda())
    {
        ucerrtime++;
        if (ucerrtime > 250)
        {
            iic_stop(p);
            return 1;
        }
    }
    p->io.wrscl(0);
    return 0;
}

// iic发送一个字节
// 返回从机有无应答
// 1，有应答
// 0，无应答
int32_t iic_send_byte(iic_t *p, uint8_t txd)
{
    uint8_t t;
    if (!p->ioinited)
        return -1;
    for (t = 0; t < 8; t++)
    {
        p->io.wrsda((txd & 0x80) ? true : false);
        p->io.dlyus(2); 
        p->io.wrscl(1);
        p->io.dlyus(2);
        p->io.wrscl(0);
        txd <<= 1;
    }
    p->io.wrsda(1);
    return 0;
}

// 读1个字节，ack=1时，发送ack，ack=0，发送nack
int32_t iic_read_byte(iic_t *p, uint8_t *rbuf, uint8_t ack)
{
    uint8_t i, receive = 0;
    if (!p->ioinited)
        return -1;
    for (i = 0; i < 8; i++)
    {
        receive <<= 1;
        p->io.wrscl(1);
        p->io.dlyus(2);
        if (p->io.rdsda())
            receive++;
        p->io.wrscl(0);
        p->io.dlyus(2);
    }
    if (!ack)
        iic_nack(p);
    else
        iic_ack(p);
    *rbuf = receive;
    return 0;
}
